<?php
/**
 *      [迷你云] (C)2009-2012 南京恒为网络科技.
 *   软件仅供研究与学习使用，如需商用，请访问www.miniyun.cn获得授权
 * 
 */
?>
<?php

class Copy extends CApiComponent
{
    private $_userNick;
    public $toId;     public $fromId;     public $fromPath;     public $toPath;     public $from;
    public $toParent;
    
    public function __construct ()
    {
        parent::init();
        $this->result = array();
        $this->result["state"] = false;
        $this->result["code"] = 0;
        $this->result["msg"] = "复制失败";
        $this->result["data"] = array();
    }
    
    private function initById ()
    {
                if ($this->toId == 0) {
            $toParent = new UserFile();
            $toParent["id"] = 0;
            $toParent["file_path"] = "/{$this->_userId}";
        } else {
            $toParent = UserFile::model()->findByPk($this->toId);
        }
                $from = UserFile::model()->findByPk($this->fromId, "is_deleted=0");
        if (is_null($from) || is_null($toParent)) {
            throw new ApiException("Not found");
        }
        $this->fromPath = $from["file_path"];
        $pathInfo = CUtils::pathinfo_utf($this->fromPath);
        $this->toPath = $toParent['file_path'] . "/" . $pathInfo["basename"];
        $this->fromPath = CUtils::convertStandardPath($this->fromPath);
        $this->toPath = CUtils::convertStandardPath($this->toPath);
        $this->from = $from;
        $this->toParent = $toParent;
    }
    
    
    private function initByPath ()
    {
                $pathInfo = CUtils::pathinfo_utf($this->toPath);
        $dirname = $pathInfo["dirname"];
        if ($dirname == "/{$this->_userId}") {
            $toParent = $toParent = new UserFile();
            $toParent["id"] = 0;
            $toParent["file_path"] = "/{$this->_userId}";
        } else {
            $toParent = UserFile::model()->findByAttributes(
            array("file_path" => $dirname));
        }
                $from = UserFile::model()->findByAttributes(
        array("file_path" => $this->fromPath, "is_deleted" => 0));
        if (is_null($from))
            throw new ApiException("Not found");
        $this->from = $from;
        $this->toParent = $toParent;
    }
    
    public function invoke ($isPath = true)
    {
                $device = new UserDevice();
        $device = $device->findByUserIdAndType($this->_userId, 1);
        $this->_deviceId = $device["id"];
        $user = User::model()->findByPk($this->_userId);
        $this->_userNick = $user["user_name"];
                                $this->handleSpace();
        if ($isPath) {
            $this->fromPath = CUtils::convertStandardPath($this->fromPath);
            $this->toPath = CUtils::convertStandardPath($this->toPath);
            $this->initByPath();
        } else {
            $this->initById();
        }
                                if ($this->fromPath === $this->toPath) {
            $this->result["data"][$this->fromId]["state"] = false;
            $this->handleResult(false, 0, "已存在同名文件");
            return;
        }
                                if (strpos($this->toPath, $this->fromPath . "/") === 0) {
            $this->result["msg"] = "不能移动到子目录";
            return;
        }
        
        if ($this->toPath == "/{$this->_userId}" ||
         $this->toPath == "/{$this->_userId}/") {
            $this->result["msg"] = "目标目录不存在";
            return;
        }
        
                                $target = UserFile::model()->findByAttributes(array("user_id"=> $this->_userId, 
                                                            "file_path"=>$this->toPath, "is_deleted" => 0));
        if ($target) {
            $this->handleResult(false, 0, "已存在同名的文件");
            return;
        }
        
                if ($this->from["file_type"] == 0) {
            $this->handleCopyFile($this->fromPath, $this->toPath);
        } else {             $this->handleCopyFolder($this->fromPath, $this->toPath);
        }
                $this->handleResult(true, 0, "复制成功");
        $this->result["data"][$this->fromId]["state"] = true;
    }
    
    private function handleCopyFile ($fromPath, $toPath)
    {
        $createFolder = new CreateFolder();
        $createFolder->_deviceId = $this->_deviceId;
        $createFolder->_userId = $this->_userId;
        $pathInfo = CUtils::pathinfo_utf($toPath);
        $parentId = $createFolder->handleCreateByPath($pathInfo["dirname"]);
                $name = $this->handleRename($parentId, $pathInfo["basename"]);
        $toPath = $pathInfo["dirname"] . "/" . $name;
        $version = FileVersion::model()->findByPk($this->from["version_id"]);
        $hash = $version["file_signature"];
                                $context = array( "hash"  => $hash,
                          "rev"   => (int)$this->from["version_id"],
                          "bytes" => (int)$this->from["file_size"]);
                                $target = UserFile::model()->findByAttributes(array("user_id"=> $this->_userId, 
                                                            "file_path"=>$this->toPath, 
                                                            "is_deleted" => 1));
        if (!$target) {
            $target = new UserFile();
            $target["user_id"]          = $this->_userId;
            $target["parent_file_id"]   = $parentId;
            $target["file_create_time"] = time();
        }
        $target["file_type"]        = 0;
        $target["is_deleted"]       = 0;
        $target["version_id"]       = $this->from["version_id"];
        $target["file_size"]        = $this->from["file_size"];
        $target["file_path"]        = $toPath;
        $target["file_name"]        = $name;
        $target["file_update_time"] = time();
        $target["event_uuid"]       = CUtils::random_string(46);
        $target->save();
        
                $this->handleFileMeta($toPath, $this->from["version_id"], $this->_userId, $this->_userNick, 3);
                $event = new UserEvent();
        $event->CreateEvent($this->_userId, $this->_deviceId, 3, $toPath, serialize($context), $target["event_uuid"]);
    }
    
    public function handleCopyFolder ($fromPath, $toPath)
    {
        $createFolder = new CreateFolder();
        $createFolder->_deviceId = $this->_deviceId;
        $createFolder->_userId = $this->_userId;
        $pathInfo = CUtils::pathinfo_utf($toPath);
        $parentId = $createFolder->handleCreateByPath($pathInfo["dirname"]);
                $name = $this->handleRename($parentId, $pathInfo["basename"]);
        $this->toPath = $pathInfo["dirname"] . "/" . $name;
        
                                $target = UserFile::model()->findByAttributes(array("user_id"=> $this->_userId, 
                                                            "file_path"=>$toPath, 
                                                            "is_deleted" => 1));
        if (!$target) {
            $target = new UserFile();
            $target["user_id"]          = $this->_userId;
            $target["parent_file_id"]   = $parentId;
            $target["file_create_time"] = time();
        }
        $target["file_type"]        = 0;
        $target["is_deleted"]       = 0;
        $target["version_id"]       = $this->from["version_id"];
        $target["file_size"]        = $this->from["file_size"];
        $target["file_path"]        = $toPath;
        $target["file_name"]        = $name;
        $target["file_update_time"] = time();
        $target["event_uuid"]       = CUtils::random_string(46);
        $target->save();
                $event = new UserEvent();
        $event->CreateEvent($this->_userId, $this->_deviceId, 0, $toPath, $context, $target["event_uuid"]);
                $handler = new UserFile();
        $children = $handler->getChildrenFileByPath($fromPath);
        foreach ($children as $child) {
            $this->from = $child;
            $childFromPath = $child["file_path"];
            $index         = strlen($this->fromPath);
            $childtoPath   = substr_replace($childFromPath,$this->toPath, 0, $index);
            $this->handleCopyFile($childFromPath, $childtoPath);
        }
        
                $folders = $handler->getChildrenFileByPath($fromPath,1);
        $createFolder = new CreateFolder();
        $createFolder->_deviceId = $this->_deviceId;
        $createFolder->_userId = $this->_userId;
        foreach ($folders as $folder) {
            $childFromPath = $child["file_path"];
            $index         = strlen($this->fromPath);
            $childtoPath   = substr_replace($childFromPath,$this->toPath, 0, $index);
            $parentId = $createFolder->handleCreateByPath($childtoPath);
        }
    }
    
    
    
    public function handleFileMeta ($filePath, $versionId, $userId, $userNick, $action)
    {
                                $handler = new FileMeta();
        $meta = $handler->getFileMeta($filePath, "version");
        if ($meta) {
            $value = CUtils::getFileVersions($versionId, $action, $userId, 
            $userNick, $meta["meta_value"]);
            $meta["meta_value"] = $value;
        } else {
            $meta = new FileMeta();
            $value = CUtils::getFileVersions($versionId, $action, $userId, 
            $userNick);
            $meta["file_path"] = $filePath;
            $meta["meta_key"] = "version";
            $meta["meta_value"] = $value;
        }
        return $meta->save();
    }
    
    private function handleRename ($parentId, $name)
    {
        $children = UserFile::model()->findAllByAttributes(
        array("parent_file_id" => $parentId, "user_id" => $this->_userId, 
        "is_deleted" => 0));
        $names = array();
        foreach ($children as $child) {
            $names[$child["file_name"]] = $child["file_name"];
        }
                $name = CUtils::getConflictName($name, $names);
        return $name;
    }
    
    public function handleException ($exception)
    {
        echo CJSON::encode($this->result);
    }
}
?>